package com.xsq.rpc.consumer.proxy;


import com.xsq.rpc.common.consumer.UserClientHandler;
import com.xsq.rpc.common.model.RPCNettyClient;
import com.xsq.rpc.common.model.RpcMapper;
import com.xsq.rpc.common.model.RpcRequest;
import com.xsq.rpc.consumer.listener.PathChildrenListener;
import com.xsq.rpc.consumer.rpc.RpcClient;
import org.omg.Messaging.SYNC_WITH_TRANSPORT;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StopWatch;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @ClassName XsqProxyFactory
 * @Description TODO
 * @Author xsq
 * @Date 2020/5/30 11:19
 **/
public class XsqProxyFactory {


    private ExecutorService executor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());

    /**
     * jdk动态代理
     *
     * @param serviceClass
     * @return
     */
    public Object createProxy(final Class<?> serviceClass) {
        return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), new Class<?>[]{serviceClass}, new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                //构建请求对象
                RpcRequest rpcRequest = RpcRequest.build(serviceClass, method, args);
                Map<String, RpcMapper> rpcmappers = PathChildrenListener.RPCMAPPERS;
                if (!CollectionUtils.isEmpty(rpcmappers)) {
                    //获取响应性能最好的服务器
                    RpcMapper rpcMapper = getLoadBalancingServer(rpcmappers);
                    if (rpcMapper == null) {
                        //随机获取一台服务器进行远程调用
                        rpcMapper = randomGetRpcMapper(rpcmappers);
                    } else {
                        System.out.println("获取到5秒内响应时间最短的服务端" + rpcMapper.getPath());
                    }
                    //获取rpc连接进行远程调用
                    UserClientHandler userClientHandler = rpcMapper.getrPCNettyClient().getUserClientHandler();
                    System.out.println("rpcMapper：" + rpcMapper + "--path：" + rpcMapper.getPath() + "-----userClientHandler：" + userClientHandler);
                    userClientHandler.setPara(rpcRequest);
                    StopWatch sw = new StopWatch();
                    sw.start();
                    String rs = (String) executor.submit(userClientHandler).get();
                    //计算调用服务端的耗时
                    sw.stop();
                    //记录服务端相应的时间戳
                    rpcMapper.setTime(System.currentTimeMillis());
                    //记录服务端对应的相应时间
                    rpcMapper.setResponseTime(sw.getTotalTimeMillis());
                    System.out.println("服务端" + rpcMapper.getPath() + "的响应时间为" + sw.getTotalTimeMillis());
                    return rs;
                }
                return null;
            }


        });
    }

    /**
     * 获取响应性能最好的服务器
     *
     * @param rpcmappers
     * @return
     */
    private RpcMapper getLoadBalancingServer(Map<String, RpcMapper> rpcmappers) {
        Map<String, Long> responseMap = new HashMap<>();
        for (Map.Entry<String, RpcMapper> map : rpcmappers.entrySet()) {
            if (map.getValue().getTime() != null && map.getValue().getResponseTime() != null) {
                responseMap.put(map.getKey(), map.getValue().getResponseTime());
            }
        }
        if (CollectionUtils.isEmpty(responseMap)) {
            return null;
        }
        Integer flag = 0;
        String url = null;
        if (responseMap.size() == 1 && rpcmappers.size() == 1) {
            flag = 0;
        } else if (responseMap.size() == 1 && rpcmappers.size() != 1) {
            return null;
        } else {
            flag = 2;
        }
        for (Map.Entry<String, Long> map : responseMap.entrySet()) {
            if (flag == 0) {
                return rpcmappers.get(map.getKey());
            } else if (flag == 2) {
                if (url == null) {
                    url = map.getKey();
                } else {
                    //当向应时间小于目前的,则更新服务端路径
                    if (map.getValue() < responseMap.get(url)) {
                        url = map.getKey();
                    }
                }
            }
        }
        return rpcmappers.get(url);
    }

    /**
     * 随机获取一台服务器进行远程调用
     *
     * @param rpcmappers
     */
    public RpcMapper randomGetRpcMapper(Map<String, RpcMapper> rpcmappers) {
        Integer size = rpcmappers.size();
        int i = 0;
        Random random = new Random();
        int rn = random.nextInt(size);
        for (String key : rpcmappers.keySet()) {
            if (i == rn) {
                return rpcmappers.get(key);
            }
            i++;
        }
        return null;
    }

}
